package com.itheima.service.impl;

import com.itheima.mapper.MemberMapper;
import com.itheima.mapper.OrderMapper;
import com.itheima.mapper.SetmealMapper;
import com.itheima.pojo.Order;
import com.itheima.pojo.Setmeal;
import com.itheima.pojo.dto.HotSetmeal;
import com.itheima.pojo.dto.Order4SetmealCountDto;
import com.itheima.pojo.vo.BusinessReportData;
import com.itheima.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Override
    public Map<String, List<String>> getMemberReport() {
        // 为了性能可以查询所有然后在排序
        List<LocalDate> dates =memberMapper.selectAllDateForCount();
        log.info("查询所有日期：{}", dates);

        Map<String, List<String>> map = new HashMap<>();
        List<String> months  = new ArrayList<>();
        List<Integer> memberCount = new ArrayList<>();
        dates.forEach(date -> {
            int capacity = months.size() - 1;
            // 没有月份时或者这个月份和上一个月份不同时，新增
            if (months.isEmpty() || !months.get(capacity).equals(date.toString())){
                months.add(date.toString());
                memberCount.add(1);
            }// 已有
            else{
                memberCount.set(capacity, memberCount.get(capacity) + 1);
            }
        });
        // 数量转为String
        List<String> collect = memberCount.stream().map(String::valueOf).collect(Collectors.toList());

        map.put("months", months);
        map.put("memberCount", collect);
        return map;
    }

    /**
     * 套餐占比
     * @return
     */
    @Override
    public Map<String, Object> getSetmealReport() {
        Map<String, Object> result = new HashMap<>();
        // 获取套餐名称和数量
        List<Order4SetmealCountDto> setmealCount = orderMapper.getSetmealCount();
        List<String> setmealNames = setmealCount.stream().map(Order4SetmealCountDto::getName).collect(Collectors.toList());
        result.put("setmealNames", setmealNames);
        result.put("setmealCount", setmealCount);
        return result;
    }

    /**
     * 运营数据
     * @return
     */
    @Override
    public BusinessReportData getBusinessReportData() {
        BusinessReportData reportData = new BusinessReportData();
        // 日期数据填充
        LocalDate today = LocalDate.now();
        LocalDate monthDay = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate weekDay = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
        reportData.setReportDate(today);

        // 会员数据填充
        // 数据获取
        // 为了性能可以查询所有然后在排序
        List<LocalDate> dates =memberMapper.selectAllDateForCount();
        int thisMonthNewMember = 0, thisWeekNewMember = 0, thisDayNewMember = 0;
        for(LocalDate date : dates) {
            if (!date.isBefore(monthDay)) thisMonthNewMember ++;
            if (!date.isBefore(weekDay)) thisWeekNewMember++;
            if (date.isEqual(today)) thisDayNewMember++;
        }
        reportData.setTodayNewMember(thisDayNewMember);
        reportData.setThisMonthNewMember(thisMonthNewMember);
        reportData.setThisWeekNewMember(thisWeekNewMember);
        reportData.setTotalMember(dates.size());

        // 预约数据填充
        int thisDayOrderNumber = 0, thisDayVisitsNumber = 0;
        int thisWeekOrderNumber = 0, thisWeekVisitsNumber = 0;
        int thisMonthOrderNumber = 0, thisMonthVisitsNumber = 0;
        for (Order order : orderMapper.selectByQueryString("")) {
            if (order.getOrderDate().isEqual(today)) {
                thisDayOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisDayVisitsNumber++;
                }
            }
            if (order.getOrderDate().isAfter(weekDay)) {
                thisWeekOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisWeekVisitsNumber++;
                }
            }
            if (order.getOrderDate().isAfter(monthDay)) {
                thisMonthOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisMonthVisitsNumber++;
                }
            }
        }
        reportData.setTodayOrderNumber(thisDayOrderNumber);
        reportData.setTodayVisitsNumber(thisDayVisitsNumber);
        reportData.setThisWeekOrderNumber(thisWeekOrderNumber);
        reportData.setThisWeekVisitsNumber(thisWeekVisitsNumber);
        reportData.setThisMonthOrderNumber(thisMonthOrderNumber);
        reportData.setThisMonthVisitsNumber(thisMonthVisitsNumber);

        // 热门套餐
        List<HotSetmeal> hotSetmeal = new ArrayList<>();
        List<Order4SetmealCountDto> setmealCount = orderMapper.getSetmealCount();
        setmealCount.sort(Comparator.comparingInt(o -> -o.getValue()));
        for (int i = 0; i < setmealCount.size() && i < 3; i++) {
            Order4SetmealCountDto orderDto = setmealCount.get(i);
            int percent = (10000 * orderDto.getValue() / dates.size());
            hotSetmeal.add(new HotSetmeal(
                    orderDto.getName(), orderDto.getValue(),
                    percent * 1.0 / 10000));
        }
        reportData.setHotSetmeal(hotSetmeal);
        return reportData;

    }

    /**
     * 导出运营数据
     * @param response
     * @return
     */
    @Override
    public Boolean exportBusinessReportData(HttpServletResponse response) {
        // 1.获取数据
        // 日期数据填充
        LocalDate today = LocalDate.now();
        LocalDate monthDay = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate weekDay = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

        // 会员数据填充
        // 数据获取
        // 为了性能可以查询所有然后在排序
        List<LocalDate> dates =memberMapper.selectAllDateForCount();
        int thisMonthNewMember = 0, thisWeekNewMember = 0, thisDayNewMember = 0;
        for(LocalDate date : dates) {
            if (!date.isBefore(monthDay)) thisMonthNewMember ++;
            if (!date.isBefore(weekDay)) thisWeekNewMember++;
            if (date.isEqual(today)) thisDayNewMember++;
        }
        // 预约数据填充
        int thisDayOrderNumber = 0, thisDayVisitsNumber = 0;
        int thisWeekOrderNumber = 0, thisWeekVisitsNumber = 0;
        int thisMonthOrderNumber = 0, thisMonthVisitsNumber = 0;
        for (Order order : orderMapper.selectByQueryString("")) {
            if (order.getOrderDate().isEqual(today)) {
                thisDayOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisDayVisitsNumber++;
                }
            }
            if (order.getOrderDate().isAfter(weekDay)) {
                thisWeekOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisWeekVisitsNumber++;
                }
            }
            if (order.getOrderDate().isAfter(monthDay)) {
                thisMonthOrderNumber++;
                if (order.getOrderStatus().equals(Order.ORDERSTATUS_YES)) {
                    thisMonthVisitsNumber++;
                }
            }
        }

        // 热门套餐
        List<HotSetmeal> hotSetmeal = new ArrayList<>();
        List<Order4SetmealCountDto> setmealCount = orderMapper.getSetmealCount();
        setmealCount.sort(Comparator.comparingInt(o -> -o.getValue()));
        for (int i = 0; i < setmealCount.size() && i < 3; i++) {
            Order4SetmealCountDto orderDto = setmealCount.get(i);
            int percent = (10000 * orderDto.getValue() / dates.size());
            hotSetmeal.add(new HotSetmeal(
                    orderDto.getName(), orderDto.getValue(),
                    percent * 1.0 / 10000));
        }


        // 2.文件操作
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("templates/" + "report_template.xlsx");
        log.info("文件操作开始{}", in);
        try {
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(Objects.requireNonNull(in));
            XSSFSheet sheetAtFirst = xssfWorkbook.getSheetAt(0);
            sheetAtFirst.getRow(2).getCell(5).setCellValue(today.toString());

            sheetAtFirst.getRow(4).getCell(5).setCellValue(thisDayNewMember);
            sheetAtFirst.getRow(4).getCell(7).setCellValue(dates.size());
            sheetAtFirst.getRow(5).getCell(5).setCellValue(thisWeekNewMember);
            sheetAtFirst.getRow(5).getCell(7).setCellValue(thisMonthNewMember);

            sheetAtFirst.getRow(7).getCell(5).setCellValue(thisDayOrderNumber);
            sheetAtFirst.getRow(7).getCell(7).setCellValue(thisDayVisitsNumber);
            sheetAtFirst.getRow(8).getCell(5).setCellValue(thisWeekOrderNumber);
            sheetAtFirst.getRow(8).getCell(7).setCellValue(thisWeekVisitsNumber);
            sheetAtFirst.getRow(9).getCell(5).setCellValue(thisMonthOrderNumber);
            sheetAtFirst.getRow(9).getCell(7).setCellValue(thisMonthVisitsNumber);

            for (int i = 0; i < hotSetmeal.size(); i++) {
                HotSetmeal hotSetmeal1 = hotSetmeal.get(i);
                XSSFRow row = sheetAtFirst.getRow(12 + i);
                row.getCell(4).setCellValue(hotSetmeal1.getName());
                row.getCell(5).setCellValue(hotSetmeal1.getSetmeal_count());
                row.getCell(6).setCellValue(hotSetmeal1.getProportion());
            }

            // 设置响应头
//            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 设置 MIME 类型为 Excel 文件
            response.setHeader("Content-Disposition", "attachment; filename=report_template.xlsx"); // 设置文件名

            OutputStream os = response.getOutputStream();
            xssfWorkbook.write(os);
            xssfWorkbook.close();
            in.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}
